<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   
      <title>3.5. C&oacute;digo de la l&oacute;gica de negocio</title>
      <meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2">
      <link rel="home" href="indice.html" title="Manual Usuario gvHidra">
      <link rel="up" href="ch03.html" title="Cap&iacute;tulo 3. Elementos b&aacute;sicos">
      <link rel="prev" href="ch03s04.html" title="3.4. Dise&ntilde;o de pantalla con smarty/plugins">
      <link rel="next" href="ch03s06.html" title="3.6. Personalizando el estilo">
   </head>
   <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
      <div class="navheader">
         <table width="100%" summary="Navigation header">
            <tr>
               <th colspan="3" align="center">3.5. C&oacute;digo de la l&oacute;gica de negocio</th>
            </tr>
            <tr>
               <td width="20%" align="left"><a accesskey="p" href="ch03s04.html">Anterior</a>&nbsp;
               </td>
               <th width="60%" align="center">Cap&iacute;tulo 3. Elementos b&aacute;sicos</th>
               <td width="20%" align="right">&nbsp;<a accesskey="n" href="ch03s06.html">Siguiente</a></td>
            </tr>
         </table>
         <hr>
      </div>
      <div class="section" title="3.5. C&oacute;digo de la l&oacute;gica de negocio">
         <div class="titlepage">
            <div>
               <div>
                  <h2 class="title" style="clear: both"><a name="d4e1949"></a>3.5. C&oacute;digo de la l&oacute;gica de negocio
                  </h2>
               </div>
            </div>
         </div>
             
         
             
         <p>En este punto entraremos en detalle del c&oacute;digo de la l&oacute;gica de
                negocio explicada en el <a class="link" href="ch02s03.html#C2LogicaNegocio">punto L&oacute;gica de
                   negocio del cap&iacute;tulo 2</a>.
         </p>
         
             
         <div class="section" title="3.5.1. Operaciones y m&eacute;todos virtuales">
            <div class="titlepage">
               <div>
                  <div>
                     <h3 class="title"><a name="d4e1953"></a>3.5.1. Operaciones y m&eacute;todos virtuales
                     </h3>
                  </div>
               </div>
            </div>
                  
            
                  
            <p>Vamos a adentranos en el c&oacute;digo para entender mejor las
                     <span class="emphasis"><em>operaciones</em></span> de gvHidra y sus <span class="emphasis"><em>m&eacute;todos
                           virtuales</em></span>, explicadas en el punto 2 del cap&iacute;tulo 1 L&oacute;gica de
                     negocio.
            </p>
            
                  
            <p>Las acciones buscar, insertar, editar, borrar, modificar... son
                     acciones generales que no contemplan las reglas de negocio particulares
                     de una aplicaci&oacute;n. Por ejemplo, si tenemos un panel que muestra
                     facturas, el programador puede utilizar la acci&oacute;n borrar para cuando un
                     usuario lo desee pueda borrar una factura. Pero, &iquest;y si quiere que s&oacute;lo
                     se borren las facturas que no est&eacute;n abonadas? Para ello debemos
                     modificar el comportamiento general de la acci&oacute;n. Esta modificaci&oacute;n se
                     har&aacute; en las clases de negocio (<span class="emphasis"><em>actions</em></span>)
                     sobreescribiendo uno de los <span class="emphasis"><em>m&eacute;todos abstractos</em></span>
                     (<span class="emphasis"><em>virtuales</em></span>) vistos anteriormente con el c&oacute;digo
                     particular que se desee introducir.
            </p>
            
                  
            <p>En general, tenemos un m&eacute;todo para antes de realizar la operaci&oacute;n,
                     que nos permite cancelarla (<span class="emphasis"><em>pre-validaci&oacute;n</em></span>) y un
                     m&eacute;todo para despu&eacute;s de la operaci&oacute;n
                     (<span class="emphasis"><em>post-validaci&oacute;n</em></span>), que se puede utilizar para
                     realizar operaciones en otras tablas.
            </p>
            
                  
            <p>M&eacute;todos virtuales:</p>
            
                  
            <div class="orderedlist">
               <ol class="orderedlist" type="1">
                  <li class="listitem">
                               
                     <p><a class="link" href="ch03s05.html#preiniciarventana">preIniciarVentana</a></p>
                             
                  </li>
                  <li class="listitem">
                               
                     <p><a class="link" href="ch03s05.html#buscar">preBuscar</a><em class="parameter"><code>,
                                        </code></em><a class="link" href="ch03s05.html#buscar">postBuscar</a></p>
                             
                  </li>
                  <li class="listitem">
                               
                     <p><a class="link" href="ch03s05.html#insertar">preInsertar</a><em class="parameter"><code>,
                                        </code></em><a class="link" href="ch03s05.html#insertar">postInsertar</a></p>
                             
                  </li>
                  <li class="listitem">
                               
                     <p><a class="link" href="ch03s05.html#nuevo">preNuevo</a></p>
                             
                  </li>
                  <li class="listitem">
                               
                     <p><a class="link" href="ch03s05.html#modificar">preModificar</a><em class="parameter"><code>,
                                        </code></em><a class="link" href="ch03s05.html#modificar">postModificar</a></p>
                             
                  </li>
                  <li class="listitem">
                               
                     <p><a class="link" href="ch03s05.html#borrar">preBorrar</a><em class="parameter"><code>,
                                        </code></em><a class="link" href="ch03s05.html#borrar">postBorrar</a></p>
                             
                  </li>
                  <li class="listitem">
                               
                     <p><a class="link" href="ch03s05.html#editar">preEditar</a><em class="parameter"><code>,
                                        </code></em><a class="link" href="ch03s05.html#editar">postEditar</a></p>
                             
                  </li>
                  <li class="listitem">
                               
                     <p><a class="link" href="ch03s05.html#recargar">preRecargar</a><em class="parameter"><code>,
                                        </code></em><a class="link" href="ch03s05.html#recargar">postRecargar</a></p>
                             
                  </li>
                  <li class="listitem">
                               
                     <p><a class="link" href="ch03s05.html#app">openApp</a><em class="parameter"><code>,
                                        </code></em><a class="link" href="ch03s05.html#app">closeApp</a></p>
                             
                  </li>
               </ol>
            </div>
            
                  
            <p>Todos estos m&eacute;todos tienen como par&aacute;metro una instancia de la
                     clase IgepComunicaUsuario que proporcionar&aacute; al programador un acceso
                     total a los datos que intervienen en la operaci&oacute;n. Este acceso a los
                     datos vendr&aacute; dado por los siguientes m&eacute;todos disponibles en cualquiera
                     de los m&eacute;todos virtuales citados:
            </p>
            
                  
            <div class="itemizedlist">
               <ul class="itemizedlist" type="disc">
                  <li class="listitem">
                               
                     <p>getValue / setValue</p>
                             
                  </li>
                  <li class="listitem">
                               
                     <p>getOldValue</p>
                             
                  </li>
                  <li class="listitem">
                               
                     <p>nextTupla</p>
                             
                  </li>
                  <li class="listitem">
                               
                     <p>currentTupla</p>
                             
                  </li>
                  <li class="listitem">
                               
                     <p>fetchTupla / setTupla</p>
                             
                  </li>
                  <li class="listitem">
                               
                     <p>getAllTuplas / setAllTuplas</p>
                             
                  </li>
                  <li class="listitem">
                               
                     <p>getAllOldTuplas</p>
                             
                  </li>
                  <li class="listitem">
                               
                     <p>getOperacion / setOperacion</p>
                             
                  </li>
               </ul>
            </div>
            
                  
            <p>Para trabajar campo por campo, en la variable $objDatos
                     ...:
            </p>
            
                  
            <div class="informalexample">
                       
               
                       <pre class="programlisting">//Devuelve el valor del campo de la fila actual

$objDatos-&gt;<span class="bold"><strong>getValue</strong></span>('nombreCampo');

//Devuelve el valor del campo antes de ser modificado 
//(ojo: devuelve el valor que tiene en la BD)

$objDatos-&gt;<span class="bold"><strong>getOldValue</strong></span>('nombreCampo');

//Fija el valor del campo de la fila actual

$objDatos-&gt;<span class="bold"><strong>setValue</strong></span>('nombreCampo','nuevoValor');

//Devuelve el registro activo sobre el origen de datos actual (cursor)

$tupla = $objDatos-&gt;<span class="bold"><strong>currentTupla</strong></span>();

//Mueve el cursor a la fila siguiente

$objDatos-&gt;<span class="bold"><strong>nextTupla</strong></span>();</pre>
                     </div>
            
                  
            <p>Para trabajar tupla a tupla:</p>
            
                  
            <div class="informalexample">
                       
               
                       <pre class="programlisting">//Devuelve un vector con el contenido de la tupla actual 
//y mueve el cursor interno

$tupla = $objDatos-&gt;<span class="bold"><strong>fetchTupla</strong></span>();

//Fija el contenido de la fila activa con el valor deseado.

$objDatos-&gt;<span class="bold"><strong>setTupla</strong></span>($tupla);</pre>
                     </div>
            
                  
            <p>Para trabajar directamente con la matriz de datos:</p>
            
                  
            <div class="informalexample">
                       
               
                       <pre class="programlisting">//Devuelve una matriz que contiene todas las tuplas que intervienen
//en la operaci&oacute;n

$m_datos = $objDatos-&gt;<span class="bold"><strong>getAllTuplas</strong></span>();

//Fija la matriz con las tuplas que intervienen en la operaci&oacute;n

$objDatos-&gt;<span class="bold"><strong>setAllTuplas</strong></span>($m_datos);

//Devuelve la matriz de registros original correspondiente al origen de datos 
//pasado como argumento (datos inserci&oacute;n, modificaci&oacute;n, borrado) o el
//preestablecido. 

$m_datos = $objDatos-&gt;<span class="bold"><strong>getAllOldTuplas</strong></span>();</pre>
                     </div>
            
                  
            <p>Para trabajar con una matriz de datos concreta (ver <a class="link" href="ch03s05.html#C3AccesoDatos">acceso a datos</a>):
            </p>
            
                  
            <div class="informalexample">
                       
               
                       <pre class="programlisting">//Fija la operaci&oacute;n que ser&aacute; origen de los datos con los que se trabajar&aacute;
//El par&aacute;metro ser&aacute; la operaci&oacute;n de la cual se quiere la matriz
//  - '<span class="emphasis"><em>visibles</em></span>': Matriz de datos visibles en la pantalla.
//  - '<span class="emphasis"><em>insertar</em></span>': Matriz de datos que ser&aacute;n insertados en la BD
//  - '<span class="emphasis"><em>actualizar</em></span>': Matriz de datos que van a ser modificados en la BD.
//  - '<span class="emphasis"><em>borrar</em></span>': Matriz de datos que ser&aacute;n borrados de la BD.
//  - '<span class="emphasis"><em>seleccionar</em></span>': Matriz de datos de la/s tupla/s seleccionada/s.
//  - '<span class="emphasis"><em>buscar</em></span>': Matriz de datos que se utilizar&aacute;n para la b&uacute;squeda.
//  - '<span class="emphasis"><em>postConsultar</em></span>': Matriz de datos despu&eacute;s de una b&uacute;squeda.
//  - '<span class="emphasis"><em>seleccionarPadre</em></span>': En patrones maestro-detalle, matriz de datos que 
//        nos dar&aacute; la tupla seleccionada del padre.
//  - '<span class="emphasis"><em>iniciarVentana</em></span>': Matriz que contiene todos los datos del REQUEST
//  - '<span class="emphasis"><em>external</em></span>': Matriz de datos con campos no relacionados con la matriz 
//        de datos.

$objDatos-&gt;<span class="bold"><strong>setOperacion</strong></span>('insertar');</pre>
                     </div>
            
                  
            <p>Este m&eacute;todo, <span class="bold"><strong>setOperacion</strong></span>, se
                     debe utilizar en el caso de que nos encontremos en una acci&oacute;n
                     particular, ya que con &eacute;l fijaremos la operaci&oacute;n sobre qu&eacute; conjunto de
                     datos queremos trabajar.
            </p>
            
                  
            <p>Puede darse el caso que para realizar ciertas validaciones
                     necesitemos datos de otro panel. Para esto tenemos una clase que permite
                     el acceso a la informaci&oacute;n de dicho panel, que se encuentra almacenada
                     en la sesi&oacute;n (IgepSession).
            </p>
            
                  
            <div class="informalexample">
                       
               
                       <pre class="programlisting">// Te devuelve un campo de la tupla seleccionada.
$campo = IgepSession::<span class="bold"><strong>dameCampoTuplaSeleccionada</strong></span>('clasePanel','nomCampo');

// Te devuelve la tupla seleccionada.
$tuplaSeleccionada = IgepSession::<span class="bold"><strong>dameTuplaSeleccionada</strong></span>('clasePanel');

// Te devuelve el valor de una propiedad particular de la clase
$propiedad = IgepSession::<span class="bold"><strong>dameVariable</strong></span>('clasePanel','propiedad');</pre>
                     </div>
            
                  
            <p>Otro de los m&eacute;todos que podemos sobreescribir es el encargado de
                     cargar par&aacute;metros en las b&uacute;squedas. Concretamente es el m&eacute;todo
                     setSearchParameters, con &eacute;l se puede indicar a la capa de negocio
                     algunas condiciones adicionales a la where que el framework no a&ntilde;ade por
                     defecto.
            </p>
            
                  
            <p>Por otra parte, desde el m&eacute;todo abstracto (virtual) se pueden
                     ejecutar sentencias SQL que actuar&aacute;n sobre la conexi&oacute;n que tenga el
                     panel por defecto, para ello tenemos el m&eacute;todo <span class="bold"><strong>consultar</strong></span>
                     (<span class="emphasis"><em>$this-&gt;consultar($select);</em></span> ) que se ejecutar&aacute;
                     con los par&aacute;metros definidos en IgepConexion.
            </p>
            
                  
            <p>Vamos a describir algunos ejemplos para los diferentes
                     <span class="emphasis"><em>m&eacute;todos virtuales</em></span>.
            </p>
            
                  
            <div class="itemizedlist">
               <ul class="itemizedlist" type="disc">
                  <li class="listitem">
                               
                     <p><a name="preiniciarventana"></a><span class="bold"><strong>Iniciar
                                        Ventana</strong></span></p>
                     
                               
                     <p>M&eacute;todo que se ejecuta al iniciar la ventana. Por ejemplo, si
                                  tenemos una misma clase manejadora que se accede desde dos entradas
                                  de men&uacute; diferentes, agregando un par&aacute;metro en la llamada podremos
                                  saber en qu&eacute; opci&oacute;n de men&uacute; ha entrado.
                     </p>
                     
                               
                     <div class="variablelist">
                        <dl>
                           <dt><span class="term"><span class="emphasis"><em>Ejemplo</em></span></span></dt>
                           <dd>
                                              
                              <p>Tenemos dos entradas de men&uacute; que llaman a la misma
                                                 clase, una con el par&aacute;metro tipoAcceso con valor A y otro con
                                                 valor B.
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">&lt;opcion titulo="Ventana Sin Modificar" descripcion="No permitimos modificar" 
url="phrame.php?action=Clase__iniciarVentana&amp;amp;tipoAcceso=A"/&gt;

&lt;opcion titulo="Ventana Con Modificar" descripcion="Permitimos modificar" 
url="phrame.php?action=Clase__iniciarVentana&amp;amp;tipoAcceso=B"/&gt;</pre>
                                                 </div>
                              
                                              
                              <p>Teniendo esto en cuenta, podemos comprobar qu&eacute; opci&oacute;n de
                                                 men&uacute; ha seleccionado para acceder y, por ejemplo, activar o no
                                                 ciertos controles.
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">public function preIniciarVentana($objDatos) {
&nbsp;&nbsp;&nbsp; $tipoAcceso = $objDatos-&gt;getValue('acceso');
    if ($tipoAcceso=='A') {
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //No puede modificar...
&nbsp;&nbsp;&nbsp; }
    else{
        //Puede modificar...
    }
&nbsp;&nbsp;&nbsp; return 0;
}</pre>
                                                 </div>
                              
                                              
                              <p>Veamos otro ejemplo donde controlamos que se visualicen
                                                 unos campos o no en el panel de b&uacute;squeda, dependiendo de si el
                                                 usuario es administrador o no. En primer lugar creamos un
                                                 m&eacute;todo <span class="bold"><strong>preIniciarVentana </strong></span>en
                                                 la claseManejadora:
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">public function preIniciarVentana($objDatos) {
        $admin = IgepSession::dameRol();
        //Almacenamos en una variable de instancia si es administrador o no.
        if($admin=='Administrador')
                $this-&gt;esAdministrador = 1;
        else
                $this-&gt;esAdministrador = 0;
        return 0;
}</pre>
                                                 </div>
                              
                                              
                              <p>Ahora en el views tenemos que asignar la variable a la
                                                 tpl:
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">$admin = IgepSession::dameVariable('&lt;claseManejadora&gt;','esAdministrador');
$s-&gt;assign('smty_administrador',$admin);</pre>
                                                 </div>
                              
                                              
                              <p>Ahora en la tpl utilizaremos la l&oacute;gica de smarty para
                                                 poder ocultar los campos:
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">{if $smty_administrador eq 1}
        {CWCampoTexto nombre="cif" editable="true" size="5" textoAsociado="CIF"} 
        {CWCampoTexto nombre="nombre" editable="true" size="40" textoAsociado="Nombre"}
{/if}</pre>
                                                 </div>
                              
                                              
                              <p>Con esto tendremos que el campo cif y nombre solo
                                                 aparecer&aacute;n si el usuario es administrador.
                              </p>
                                            
                           </dd>
                        </dl>
                     </div>
                             
                  </li>
               </ul>
            </div>
            
                  
            <div class="itemizedlist">
               <ul class="itemizedlist" type="disc">
                  <li class="listitem">
                               
                     <p><a name="insertar"></a><span class="bold"><strong>Insertar</strong></span></p>
                     
                               
                     <p>Por defecto se insertan todas las tuplas que el usuario ha
                                  introducido en el panel. Con los m&eacute;todos <span class="bold"><strong>preInsertar</strong></span>, poder validar si se continua o
                                  no con la operaci&oacute;n, y <span class="bold"><strong>postInsertar</strong></span>, poder realizar operaciones
                                  posteriores a la inserci&oacute;n, controlaremos el funcionamiento
                                  particular de este proceso.
                     </p>
                     
                               
                     <div class="variablelist">
                        <dl>
                           <dt><span class="term"><span class="emphasis"><em>Ejemplo</em></span></span></dt>
                           <dd>
                                              
                              <p>En <span class="emphasis"><em>preInsertar</em></span> se comprueba que
                                                 todas las facturas que se han introducido correspondan a un
                                                 proveedor v&aacute;lido.
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">public function preInsertar($objDatos) 
{
   while($tupla = $objDatos-&gt;fetchTupla()) 
   {
        //Comprobamos que el cif y el orden pertenecen o a un proveedor o a una factura 
        $str_selectCAj = "SELECT count(1) as \"cuenta\" FROM tcom_proveed 
        WHERE nif = '" .$tupla['cif']."' AND orden = ".$tupla['orden']; 
        $resCAj = $this-&gt;consultar($str_selectCAj);
        if($resCAj[0]['cuenta']!=1)
        {
           //Error de validaci&oacute;n
           $this-&gt;showMensaje('APL-24');
           return -1;
        }
   }
   return 0;
}</pre>
                                                 </div>
                              
                                              
                              <p>Otro ejemplo t&iacute;pico es el del c&aacute;lculo de secuencias. En
                                                 el siguiente ejemplo mostramos como se calcula el n&uacute;mero de
                                                 secuencia de nuevas facturas dependiendo del a&ntilde;o.
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">public function preInsertar($objDatos) 
{
    //Para que cuando insertas dar el autonum&eacute;rico
    $secFacturas['anyo']=$objDatos-&gt;getValue('anyo');
    $numEntrada = $this-&gt;calcularSecuencia('tinv_facturas','nfactura',$secFacturas);
    do 
    {
        $objDatos-&gt;setValue('nfactura',$numEntrada);
        $numEntrada++;
    } while($objDatos-&gt;nextTupla());
    return 0;
}//Fin de PreInsertar</pre>
                                                 </div>
                              
                                              
                              <p>El <span class="emphasis"><em>postInsertar </em></span>se ha utilizado
                                                 para mandar un correo despu&eacute;s de la inserci&oacute;n del registro en
                                                 la tabla:
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">public function postInsertar($objDatos) 
{                                                                      
  global $g_dsn_oracle;
  $conexionOracle = new IgepConexion($g_dsn_oracle);

  $indice = key($m_datos);                              
  if ($objDatos-&gt;getValue('dgral')!='' &amp;&amp; $objDatos-&gt;getValue('cserv')!='')) 
        $nombreServDgral = $conexionOracle-&gt;consultar("select ddg as \"nombreDgral\",dservc as \"nombreServicio\" 
                                                      from vcmn_organoso where cdgo='".$objDatos-&gt;getValue('dgral')."' 
                                                      and cservo='".$objDatos-&gt;getValue('cserv')."'");
  
  //Obtenemos los datos de la clave inform&aacute;tica,el n&uacute;mero reset y el nombre del expediente
  if ($objDatos-&gt;getValue('codexp')!='') 
  {
        $claveinf = $conexionOracle-&gt;consultar("select numero_reset as \"numreset\",cianyo as \"cianyo\",cidg as \"cidg\",
                                              cinum as \"cinum\",citipo as \"citipo\",cinumtipo as \"cinumtipo\",
                                              objeto as \"nombre_exp\" 
                                              from vopu_todos_exped where claveseg='".$objDatos-&gt;getValue('codexp')."'");
        if(count($claveinf)&lt;=0) 
        {
                $this-&gt;showMensaje('APL-18');
                return -1;
        }
  }

  //Para poder obtener los datos del usuario de la sesi&oacute;n
  $datosusuario=IgepSession::dameDatosUsuario();

  //Formamos el asunto del mensaje:
  $asunto=$objDatos-&gt;getValue('aplicacion')."/".$datosusuario['nombre'];
                ...

  return parent::envioCorreo($m_datos,$rol,$indice,$datosusuario,$asunto,$texto);

}//Fin de postInsertar</pre>
                                                 </div>
                              
                                              
                              <p>Otro ejemplo de postInsertar puede ser que al insertar
                                                 en una tabla maestro queramos que se realice una inserci&oacute;n en
                                                 una tabla detalle dependiente (entidad d&eacute;bil). Tras realizar
                                                 esto, por ejemplo, podemos decidir salir de la pantalla con un
                                                 actionForward de salida, indicado para este caso
                                                 especial.
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">public function postInsertar($objDatos) 
{                                                                      
  global $g_dsn_oracle;
  $conexionOracle = new IgepConexion($g_dsn_oracle);
  
  $error = $conexionOracle-&gt;operar("INSERT INTO tabla2 VALUES (1,2)");
  if($error==-1)
  {
    $this-&gt;obj_errorNegocio-&gt;setError("APL-15","TinvLineas2.php","postInsertar");
    return -1;
  }
  else
    return $objDatos-&gt;getForward('salir');
}//Fin de postInsertar</pre>
                                                 </div>
                                            
                           </dd>
                        </dl>
                     </div>
                             
                  </li>
                  <li class="listitem">
                               
                     <p><a name="nuevo"></a><span class="bold"><strong>Nuevo</strong></span></p>
                     
                               
                     <p>Tenemos el m&eacute;todo <span class="bold"><strong>preNuevo</strong></span>,
                                  que cuando accedemos a un panel en el que vamos a introducir datos
                                  nuevos para insertar, nos va a permitir preparar algunos datos o
                                  visualizaci&oacute;n de datos, previos a la inserci&oacute;n, por ejemplo, cuando
                                  tenemos alg&uacute;n campo que tiene un valor por defecto o es calculado a
                                  partir de los valores de otros campos.
                     </p>
                     
                               
                     <div class="variablelist">
                        <dl>
                           <dt><span class="term"><span class="emphasis"><em>Ejemplo</em></span></span></dt>
                           <dd>
                                              
                              <p>Tenemos un campo secuencial que no debe ser introducido
                                                 por el usuario.
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">public function preNuevo($objDatos)
{
   $secuencia = $this-&gt;calcularSecuencia('tinv_tipo_bajas','cbaja',array());
   $objDatos-&gt;setValue('codigoBaja',$secuencia);
   return 0;
}</pre>
                                                 </div>
                                            
                           </dd>
                        </dl>
                     </div>
                             
                  </li>
                  <li class="listitem">
                               
                     <p><a name="modificar"></a><span class="bold"><strong>Modificar</strong></span></p>
                     
                               
                     <p>Por defecto, en gvHidra, se realiza la actualizaci&oacute;n de todas
                                  las tuplas que el usuario ha modificado en el panel. Con los m&eacute;todos
                                  abstractos <span class="bold"><strong>preModificar</strong></span> y <span class="bold"><strong>postModificar</strong></span> podremos modificar este
                                  comportamiento.
                     </p>
                     
                               
                     <div class="variablelist">
                        <dl>
                           <dt><span class="term"><span class="emphasis"><em>Ejemplo</em></span></span></dt>
                           <dd>
                                              
                              <p>Comprobaremos en <span class="emphasis"><em>preModificar</em></span> si la
                                                 factura tiene fecha de certificaci&oacute;n, en cuyo caso no se puede
                                                 modificar, notific&aacute;ndose al usuario con un mensaje. (Nota: por
                                                 dise&ntilde;o, en este caso solo se permite la modificaci&oacute;n de una
                                                 factura cada vez, $m_datos solo contiene una tupla)
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">public function preModificar($objDatos) 
{
    $indice = key($m_datos);
    if ($objDatos-&gt;getValue('fcertificacion')!="") 
    {
       $this-&gt;showMensaje('APL-12'); 
       return -1;
    }
    return 0;
}</pre>
                                                 </div>
                              
                                              
                              <p>Otro de los ejemplos puede ser el caso de que tengamos
                                                 que comprobar el estado de una variable del maestro
                                                 (utilizaremos la clase IgepSession) antes de operar en el
                                                 detalle. En el ejemplo comprobamos el valor de la variable
                                                 certificada del maestro para saber si se pueden modificar las
                                                 l&iacute;neas de una factura. Si es as&iacute;, forzamos a que la
                                                 descripci&oacute;n de las l&iacute;neas se almacenen en may&uacute;sculas.
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">public function preModificar($objDatos)
{
    //Comprobamos si est&aacute; la factura certificada... en este caso cancelamos la operacion
    $fechaCertif = IgepSession::dameCampoTuplaSeleccionada('TinvEntradas2','fcertificacion');
    if ($fechaCertif!="") 
    {
       $this-&gt;showMensaje('APL-12');
       return -1;
    }
    $m_datos = $objDatos-&gt;getAllTuplas();
    foreach($m_datos as $indice =&gt; $tupla) 
    {
        $m_datos[$indice]["dlinea"] = strtoupper($tupla["dlinea"]);
    }
    $objDatos-&gt;setAllTuplas($m_datos);
    return 0;
}//Fin de preModificar</pre>
                                                 </div>
                              
                                              
                              <p>El <span class="emphasis"><em>postInsertar </em></span>se ha utilizado
                                                 para mandar un correo despu&eacute;s de la inserci&oacute;n del registro en
                                                 la tabla:
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">public function postInsertar($objDatos) 
{                                                                      
  global $g_dsn_oracle;
  $conexionOracle = new IgepConexion($g_dsn_oracle);

  $indice = key($m_datos);                              
  if ($objDatos-&gt;getValue('dgral')!='' &amp;&amp; $objDatos-&gt;getValue('cserv')!='')) 
        $nombreServDgral = $conexionOracle-&gt;consultar("select ddg as \"nombreDgral\",dservc as \"nombreServicio\" 
                                                      from vcmn_organoso where cdgo='".$objDatos-&gt;getValue('dgral')."' 
                                                      and cservo='".$objDatos-&gt;getValue('cserv')."'");
  
  //Obtenemos los datos de la clave inform&aacute;tica,el n&uacute;mero reset y el nombre del expediente
  if ($objDatos-&gt;getValue('codexp')!='') 
  {
        $claveinf = $conexionOracle-&gt;consultar("select numero_reset as \"numreset\",cianyo as \"cianyo\",cidg as \"cidg\",
                                              cinum as \"cinum\",citipo as \"citipo\",cinumtipo as \"cinumtipo\",
                                              objeto as \"nombre_exp\" 
                                              from vopu_todos_exped where claveseg='".$objDatos-&gt;getValue('codexp')."'");
        if(count($claveinf)&lt;=0) 
        {
                $this-&gt;showMensaje('APL-18');
                return -1;
        }
  }

  //Para poder obtener los datos del usuario de la sesi&oacute;n
  $datosusuario=IgepSession::dameDatosUsuario();

  //Formamos el asunto del mensaje:
  $asunto=$objDatos-&gt;getValue('aplicacion')."/".$datosusuario['nombre'];
                ...

  return parent::envioCorreo($m_datos,$rol,$indice,$datosusuario,$asunto,$texto);

}//Fin de postInsertar</pre>
                                                 </div>
                              
                                              
                              <p>Otro ejemplo de postInsertar puede ser que al insertar
                                                 en una tabla maestro queramos que se realice una inserci&oacute;n en
                                                 una tabla detalle dependiente (entidad d&eacute;bil). Tras realizar
                                                 esto, por ejemplo, podemos decidir salir de la pantalla con un
                                                 actionForward de salida, indicado para este caso
                                                 especial.
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">public function postInsertar($objDatos) 
{                                                                      
  global $g_dsn_oracle;
  $conexionOracle = new IgepConexion($g_dsn_oracle);
  
  $error = $conexionOracle-&gt;operar("INSERT INTO tabla2 VALUES (1,2)");
  if($error==-1)
  {
    $this-&gt;obj_errorNegocio-&gt;setError("APL-15","TinvLineas2.php","postInsertar");
    return -1;
  }
  else
    return $objDatos-&gt;getForward('salir');
}//Fin de postInsertar</pre>
                                                 </div>
                                            
                           </dd>
                        </dl>
                     </div>
                             
                  </li>
                  <li class="listitem">
                               
                     <p><a name="borrar"></a><span class="bold"><strong>Borrar</strong></span></p>
                     
                               
                     <p>Con los m&eacute;todos <span class="bold"><strong>preBorrar </strong></span>y
                                  <span class="bold"><strong>postBorrar</strong></span> modificaremos el
                                  comportamiento de la operaci&oacute;n borrado.
                     </p>
                     
                               
                     <div class="variablelist">
                        <dl>
                           <dt><span class="term"><span class="emphasis"><em>Ejemplo</em></span></span></dt>
                           <dd>
                                              
                              <p>Vamos a simular el comportamiento de un borrado en
                                                 cascada. Es decir, si se borra una tupla de la tabla
                                                 &#8220;maestra&#8221;, se borrar&aacute;n todas las tuplas de la tabla &#8220;detalle&#8221;.
                                                 En este caso se borran todas las l&iacute;neas de una factura antes
                                                 de que se borre la factura.
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">public function preBorrar($objDatos)
{
    $this-&gt;operar("DELETE FROM tinv_bienes WHERE 
        anyo ='".$objDatos-&gt;getValue("anyo")."' and nfactura=".$objDatos-&gt;getValue("nfactura")." ");
    $errores = $this-&gt;obj_errorNegocio-&gt;hayError();
    if($errores)
    { 
        $this-&gt;showMensaje($this-&gt;obj_errorNegocio-&gt;getError());
        $this-&gt;obj_errorNegocio-&gt;limpiarError();
        return -1;
    } 
    return 0;
}//Fin de preBorrar</pre>
                                                 </div>
                              
                                              
                              <p>Otro de los ejemplos puede ser el caso de que tengamos
                                                 que comprobar el estado de una variable del maestro
                                                 (utilizaremos la clase IgepSession) antes de operar en el
                                                 detalle. En el ejemplo comprobamos el valor de la variable
                                                 certificada del maestro para saber si se pueden modificar las
                                                 l&iacute;neas de una factura. Si es as&iacute;, forzamos a que la
                                                 descripci&oacute;n de las l&iacute;neas se almacenen en may&uacute;sculas.
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">public function preModificar($objDatos)
{
    //Comprobamos si est&aacute; la factura certificada... en este caso cancelamos la operacion
    $fechaCertif = IgepSession::dameCampoTuplaSeleccionada('TinvEntradas2','fcertificacion');
    if ($fechaCertif!="") 
    {
       $this-&gt;showMensaje('APL-12');
       return -1;
    }
    $m_datos = $objDatos-&gt;getAllTuplas();
    foreach($m_datos as $indice =&gt; $tupla) 
    {
        $m_datos[$indice]["dlinea"] = strtoupper($tupla["dlinea"]);
    }
    $objDatos-&gt;setAllTuplas($m_datos);
    return 0;
}//Fin de preModificar</pre>
                                                 </div>
                              
                                              
                              <p>El <span class="emphasis"><em>postInsertar </em></span>se ha utilizado
                                                 para mandar un correo despu&eacute;s de la inserci&oacute;n del registro en
                                                 la tabla:
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">public function postInsertar($objDatos) 
{                                                                      
  global $g_dsn_oracle;
  $conexionOracle = new IgepConexion($g_dsn_oracle);

  $indice = key($m_datos);                              
  if ($objDatos-&gt;getValue('dgral')!='' &amp;&amp; $objDatos-&gt;getValue('cserv')!='')) 
        $nombreServDgral = $conexionOracle-&gt;consultar("select ddg as \"nombreDgral\",dservc as \"nombreServicio\" 
                                                      from vcmn_organoso where cdgo='".$objDatos-&gt;getValue('dgral')."' 
                                                      and cservo='".$objDatos-&gt;getValue('cserv')."'");
  
  //Obtenemos los datos de la clave inform&aacute;tica,el n&uacute;mero reset y el nombre del expediente
  if ($objDatos-&gt;getValue('codexp')!='') 
  {
        $claveinf = $conexionOracle-&gt;consultar("select numero_reset as \"numreset\",cianyo as \"cianyo\",cidg as \"cidg\",
                                              cinum as \"cinum\",citipo as \"citipo\",cinumtipo as \"cinumtipo\",
                                              objeto as \"nombre_exp\" 
                                              from vopu_todos_exped where claveseg='".$objDatos-&gt;getValue('codexp')."'");
        if(count($claveinf)&lt;=0) 
        {
                $this-&gt;showMensaje('APL-18');
                return -1;
        }
  }

  //Para poder obtener los datos del usuario de la sesi&oacute;n
  $datosusuario=IgepSession::dameDatosUsuario();

  //Formamos el asunto del mensaje:
  $asunto=$objDatos-&gt;getValue('aplicacion')."/".$datosusuario['nombre'];
                ...

  return parent::envioCorreo($m_datos,$rol,$indice,$datosusuario,$asunto,$texto);

}//Fin de postInsertar</pre>
                                                 </div>
                              
                                              
                              <p>Otro ejemplo de postInsertar puede ser que al insertar
                                                 en una tabla maestro queramos que se realice una inserci&oacute;n en
                                                 una tabla detalle dependiente (entidad d&eacute;bil). Tras realizar
                                                 esto, por ejemplo, podemos decidir salir de la pantalla con un
                                                 actionForward de salida, indicado para este caso
                                                 especial.
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">public function postInsertar($objDatos) 
{                                                                      
  global $g_dsn_oracle;
  $conexionOracle = new IgepConexion($g_dsn_oracle);
  
  $error = $conexionOracle-&gt;operar("INSERT INTO tabla2 VALUES (1,2)");
  if($error==-1)
  {
    $this-&gt;obj_errorNegocio-&gt;setError("APL-15","TinvLineas2.php","postInsertar");
    return -1;
  }
  else
    return $objDatos-&gt;getForward('salir');
}//Fin de postInsertar</pre>
                                                 </div>
                                            
                           </dd>
                        </dl>
                     </div>
                             
                  </li>
                  <li class="listitem">
                               
                     <p><a name="editar"></a><span class="bold"><strong>Editar</strong></span></p>
                     
                               
                     <p>La operaci&oacute;n de edici&oacute;n se lanza cuando se pasa de modo
                                  tabular a modo ficha en un panel mediante la acci&oacute;n &#8220;modificar&#8221;.
                                  Para ello se dispone de dos m&eacute;todos: <span class="bold"><strong>preEditar</strong></span> y <span class="bold"><strong>postEditar</strong></span>. El m&eacute;todo <span class="emphasis"><em>preEditar
                                        </em></span>recibe como par&aacute;metro de entrada las tuplas que se han
                                  seleccionado para pasar al modo ficha. Y el m&eacute;todo
                                  <span class="emphasis"><em>postEditar </em></span>recibe como par&aacute;metro de entrada el
                                  resultado de la consulta realizada, de modo que se le pueden a&ntilde;adir
                                  tuplas o campos.
                     </p>
                     
                               
                     <div class="variablelist">
                        <dl>
                           <dt><span class="term"><span class="emphasis"><em>Ejemplo</em></span></span></dt>
                           <dd>
                                              
                              <p>Vamos a comprobar que s&oacute;lo se pueda modificar un
                                                 expediente si su estado es &#8220;completado&#8221;.
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">public function preEditar($objDatos)
{
   while($tupla = $objDatos-&gt;fetchTupla())
   {
      if($tupla['estado']!='completado') 
      {
          $this-&gt;showMensaje('APL-14');
          return -1;
      }         
   }//Fin de foreach
   return 0;
}</pre>
                                                 </div>
                              
                                              
                              <p>Otro ejemplo donde vamos a crear un campo de tipo lista
                                                 para que el usuario pueda introducirlo. El campo unidadesBaja
                                                 lo tiene que crear el programador e incluirlo en el resultado
                                                 de la consulta para cada uno de los registros que se hayan
                                                 seleccionado.
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">public function postEditar($objDatos)
{
   //Cargamos una lista para cada una de las tuplas con los bienes que puede dar de baja
   $m_datos = $objDatos-&gt;getAllTuplas();
   foreach($m_datos as $indice =&gt; $linea)
   {      
        $listaBajas = new gvHidraList('unidadesBaja');
        $i=1;
        while($i&lt;=$m_datos[$indice]['unidadesDisp']) 
        {
                $listaBajas-&gt;addOption("$i","$i");
                $i++;
        }
        $m_datos[$indice]['unidadesBaja'] = $listaBajas-&gt;construyeLista();
   }//Fin de foreach
   $objDatos-&gt;setAllTuplas($m_datos);
   return 0;
}</pre>
                                                 </div>
                              
                                              
                              <p>El <span class="emphasis"><em>postInsertar </em></span>se ha utilizado
                                                 para mandar un correo despu&eacute;s de la inserci&oacute;n del registro en
                                                 la tabla:
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">public function postInsertar($objDatos) 
{                                                                      
  global $g_dsn_oracle;
  $conexionOracle = new IgepConexion($g_dsn_oracle);

  $indice = key($m_datos);                              
  if ($objDatos-&gt;getValue('dgral')!='' &amp;&amp; $objDatos-&gt;getValue('cserv')!='')) 
        $nombreServDgral = $conexionOracle-&gt;consultar("select ddg as \"nombreDgral\",dservc as \"nombreServicio\" 
                                                      from vcmn_organoso where cdgo='".$objDatos-&gt;getValue('dgral')."' 
                                                      and cservo='".$objDatos-&gt;getValue('cserv')."'");
  
  //Obtenemos los datos de la clave inform&aacute;tica,el n&uacute;mero reset y el nombre del expediente
  if ($objDatos-&gt;getValue('codexp')!='') 
  {
        $claveinf = $conexionOracle-&gt;consultar("select numero_reset as \"numreset\",cianyo as \"cianyo\",cidg as \"cidg\",
                                              cinum as \"cinum\",citipo as \"citipo\",cinumtipo as \"cinumtipo\",
                                              objeto as \"nombre_exp\" 
                                              from vopu_todos_exped where claveseg='".$objDatos-&gt;getValue('codexp')."'");
        if(count($claveinf)&lt;=0) 
        {
                $this-&gt;showMensaje('APL-18');
                return -1;
        }
  }

  //Para poder obtener los datos del usuario de la sesi&oacute;n
  $datosusuario=IgepSession::dameDatosUsuario();

  //Formamos el asunto del mensaje:
  $asunto=$objDatos-&gt;getValue('aplicacion')."/".$datosusuario['nombre'];
                ...

  return parent::envioCorreo($m_datos,$rol,$indice,$datosusuario,$asunto,$texto);

}//Fin de postInsertar</pre>
                                                 </div>
                              
                                              
                              <p>Otro ejemplo de postInsertar puede ser que al insertar
                                                 en una tabla maestro queramos que se realice una inserci&oacute;n en
                                                 una tabla detalle dependiente (entidad d&eacute;bil). Tras realizar
                                                 esto, por ejemplo, podemos decidir salir de la pantalla con un
                                                 actionForward de salida, indicado para este caso
                                                 especial.
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">public function postInsertar($objDatos) 
{                                                                      
  global $g_dsn_oracle;
  $conexionOracle = new IgepConexion($g_dsn_oracle);
  
  $error = $conexionOracle-&gt;operar("INSERT INTO tabla2 VALUES (1,2)");
  if($error==-1)
  {
    $this-&gt;obj_errorNegocio-&gt;setError("APL-15","TinvLineas2.php","postInsertar");
    return -1;
  }
  else
    return $objDatos-&gt;getForward('salir');
}//Fin de postInsertar</pre>
                                                 </div>
                                            
                           </dd>
                        </dl>
                     </div>
                             
                  </li>
                  <li class="listitem">
                               
                     <p><a name="recargar"></a><span class="bold"><strong>Recargar</strong></span></p>
                     
                               
                     <p>Esta acci&oacute;n se realiza cuando vamos a mostrar la informaci&oacute;n
                                  de un panel que depende de otro, es decir, cuando vamos a mostrar la
                                  informaci&oacute;n de un detalle en un maestro-detalle. Se proporcionan dos
                                  m&eacute;todos para parametrizar esta acci&oacute;n: <span class="bold"><strong>preRecargar</strong></span> y <span class="bold"><strong>postRecargar</strong></span>. El primero recibe como
                                  par&aacute;metro la selecci&oacute;n del maestro, y el segundo el resultado de la
                                  consulta.
                     </p>
                     
                               
                     <div class="variablelist">
                        <dl>
                           <dt><span class="term"><span class="emphasis"><em>Ejemplo</em></span></span></dt>
                           <dd>
                                              
                              <p>Vamos a mostrar como recargar un detalle que no est&eacute;
                                                 compuesto de una select. En este caso, cargamos el
                                                 obj_ultimaConsulta (objeto que contiene lo que se va a mostrar
                                                 en pantalla) con una matriz de datos que tenemos previamente
                                                 cargada en la clase. Al tratarse de un detalle, esta matriz de
                                                 datos depender&aacute; de la selecci&oacute;n realizada en el padre. En
                                                 nuestro ejemplo el campo clave es ccentro, y la estructura de
                                                 la variable l&iacute;neas es una matriz del modo
                                                 [ccentro][indice][campo]. De modo que al cambiar el ccentro,
                                                 s&oacute;lo mostraremos las l&iacute;neas que correspondan a dicho
                                                 centro.
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">public function postRecargar($objDatos)
{
   $ccentroSeleccionado = $objDatos-&gt;getValue('ccentro','seleccionarPadre');
   $lineas = IgepSession::dameVariable('InvCabCertificadosBaja','lineasCertificados');
   $objDatos-&gt;setAllTuplas($lineas[$ccentroSeleccionado]);
   return 0;
}</pre>
                                                 </div>
                                            
                           </dd>
                        </dl>
                     </div>
                             
                  </li>
                  <li class="listitem">
                               
                     <p><a name="buscar"></a><span class="bold"><strong>Buscar</strong></span></p>
                     
                               
                     <p>El m&eacute;todo <span class="bold"><strong>preBuscar</strong></span> se
                                  dispara antes de que se realice la consulta de b&uacute;squeda (la que
                                  viene del modo b&uacute;squeda). Recibe como par&aacute;metro un objeto
                                  <span class="emphasis"><em>IgepComunicaUsuario</em></span>, que permite al programador
                                  navegar a trav&eacute;s de los datos que el usuario ha introducido en el
                                  modo de b&uacute;squeda. As&iacute;, y haciendo uso de m&eacute;todos como
                                  <span class="emphasis"><em>setSearchParameters</em></span>, el programador puede
                                  a&ntilde;adir restricciones a la consulta a realizar como EXISTS o 'fecha
                                  BETWEEN fechaInicio AND fechaFin'
                     </p>
                     
                               
                     <p>El m&eacute;todo <span class="emphasis"><em>postBuscar</em></span> recibe el mismo
                                  par&aacute;metro pero con el resultado de la consulta realizada, de modo
                                  que se puede modificar el contenido de dicha matriz de datos
                                  a&ntilde;adiendo y/o quitando registros y/o campos.
                     </p>
                     
                               
                     <p>Los m&eacute;todos relativos a la b&uacute;squeda est&aacute;n comentados en
                                  profundidad en la secci&oacute;n del uso del panel de b&uacute;squeda.
                     </p>
                             
                  </li>
                  <li class="listitem">
                               
                     <p><a name="app"></a><span class="bold"><strong>Abrir y cerrar
                                        aplicaci&oacute;n</strong></span></p>
                     
                               
                     <p>El framework ofrece la posibilidad de ejecutar c&oacute;digo antes de
                                  abrir y cerrar una ventana. Para ello, tendremos que hacer uso de
                                  una clase manejadora especial que se encargar&aacute; de controlar el panel
                                  principal (pantalla de entrada). En esta clase, podemos
                                  sobreescribir los m&eacute;todos <span class="bold"><strong>openApp </strong></span>y
                                  <span class="bold"><strong>closeApp</strong></span>, y modificar el
                                  comportamiento.
                     </p>
                     
                               
                     <div class="variablelist">
                        <dl>
                           <dt><span class="term"><span class="emphasis"><em>Ejemplo 1</em></span></span></dt>
                           <dd>
                                              
                              <p>Mostraremos como a&ntilde;adir un mensaje al iniciar la
                                                 aplicaci&oacute;n (m&eacute;todo <span class="emphasis"><em>openApp</em></span>)
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">class AppMainWindow extends CustomMainWindow
{
   public function AppMainWindow()
   {
        parent::__construct();
        //Cargamos propiedades espec&iacute;ficas del CS
        //Cuando estamos en desarrollo registramos todos los movimientos
        $conf = ConfigFramework::getConfig();
        $conf-&gt;setLogStatus(LOG_NONE);
        $conf-&gt;setQueryMode(2);
    }

    public function openApp()
    {
       $this-&gt;showMensaje('APL-31');
       return 0;
    }
} //Fin de AppMainWindow</pre>
                                                 </div>
                                            
                           </dd>
                           <dt><span class="term"><span class="emphasis"><em>Ejemplo 2</em></span></span></dt>
                           <dd>
                                              
                              <p>Mostraremos como redireccionar la entrada. Este ejemplo
                                                 recrear como redirigir la entrada en caso de que el usuario
                                                 conectado tenga el password caducado
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">class AppMainWindow extends CustomMainWindow
{
   public function AppMainWindow()
   {
        parent::__construct();
        //Cargamos propiedades espec&iacute;ficas del CS
        //Cuando estamos en desarrollo registramos todos los movimientos
        $conf = ConfigFramework::getConfig();
        $conf-&gt;setLogStatus(LOG_NONE);
        $conf-&gt;setQueryMode(2);
    }

    public function openApp()
    {
       //Validez de la entrada
       $conf = ConfigFramework::getConfig();
       $g_dsn = $conf-&gt;getDSN('g_dsn');
       $con = new IgepConexion($g_dsn);
       $res = $con-&gt;consultar('SELECT caducidad FROM tcat_usuarios WHERE id =\''.$usuario.'\'',array('DATATYPES'=&gt;array('caducidad'=&gt;TIPO_FECHA)));
       $ahora = new gvHidraTimestamp('now');
       if($res[0]['caducidad']&lt;$ahora){
           <span class="bold"><strong>$fw = $objDatos-&gt;getForward('pwdCaducado');</strong></span>
           <span class="bold"><strong>return $fw;</strong></span>
       }
       return 0;
    }
} //Fin de AppMainWindow</pre>
                                                 </div>
                              
                                              
                              <p>Previamente, en el fichero mappings.php se ha definido
                                                 el siguiente forward
                              </p>
                              
                                              
                              <div class="informalexample">
                                                   
                                 
                                                   <pre class="programlisting">$this-&gt;_AddForward('abrirAplicacion', '<span class="bold"><strong>pwdCaducado</strong></span>', 'phrame.php?action=CambioPassword__buscar&amp;caducidad=1');</pre>
                                                 </div>
                                            
                           </dd>
                        </dl>
                     </div>
                             
                  </li>
               </ul>
            </div>
            
                  
            <div class="section" title="3.5.1.1.">
               <div class="titlepage"></div>
            </div>
                
         </div>
         
             
         <div class="section" title="3.5.2. Uso del panel de b&uacute;squeda">
            <div class="titlepage">
               <div>
                  <div>
                     <h3 class="title"><a name="d4e2268"></a>3.5.2. Uso del panel de b&uacute;squeda
                     </h3>
                  </div>
               </div>
            </div>
                  
            
                  
            <div class="section" title="3.5.2.1. &iquest;Qu&eacute; hace la acci&oacute;n buscar?">
               <div class="titlepage">
                  <div>
                     <div>
                        <h4 class="title"><a name="d4e2270"></a>3.5.2.1. &iquest;Qu&eacute; hace la acci&oacute;n buscar?
                        </h4>
                     </div>
                  </div>
               </div>
                       
               
                       
               <p><span class="emphasis"><em>Buscar</em></span> es la encargada de construir la
                          consulta (SELECT) del panel utilizando los campos del panel para
                          construir la WHERE, creando una cadena del tipo campo=valor si estos
                          campos no son vac&iacute;os, para que esta cadena se cree es necesario que
                          los campos del panel de b&uacute;squeda est&eacute;n definidos con el m&eacute;todo
                          <span class="bold"><strong>addMatching()</strong></span> en la clase de negocio
                          correspondiente al panel. Los m&eacute;todos para realizar esta b&uacute;squeda son:
                          <a class="link" href="ch03s02.html#busqueda">setSelectForSearchQuery(),
                             setWhereForSearchQuery() y setOrderByForSearchQuery()</a>.
               </p>
               
                       
               <p>La acci&oacute;n de buscar, tal y como se ha comentado en el punto
                          anterior <a class="link" href="ch03s05.html#buscar">Operaciones y m&eacute;todos
                             virtuales</a>, el programador dispone de dos m&eacute;todos que puede
                          sobrescribir para parametrizar el comportamiento de la b&uacute;squeda,
                          <span class="bold"><strong>preBuscar()</strong></span> y <span class="bold"><strong>postBuscar()</strong></span>. El primero nos puede servir para
                          modificar la SELECT antes de lanzarla (a&ntilde;adir constantes, a&ntilde;adir un
                          filtro a la WHERE,...) o para impedir la realizaci&oacute;n de la consulta.
                          El segundo puede servir, por ejemplo, para a&ntilde;adir columnas adicionales
                          al DBResult obtenido.
               </p>
                     
            </div>
            
                  
            <div class="section" title="3.5.2.2. &iquest;Qu&eacute; tipos de b&uacute;squeda realiza internamente gvHidra? &iquest;C&oacute;mo puedo cambiarlos?">
               <div class="titlepage">
                  <div>
                     <div>
                        <h4 class="title"><a name="d4e2280"></a>3.5.2.2. &iquest;Qu&eacute; tipos de b&uacute;squeda realiza internamente gvHidra? &iquest;C&oacute;mo
                                   puedo cambiarlos?
                        </h4>
                     </div>
                  </div>
               </div>
                       
               
                       
               <p>Tal y como se ha comentado en el apartado anterior, gvHidra crea
                          una cadena que a&ntilde;ade al WHERE de la consulta del panel con los datos
                          que ha introducido el usuario desde el modo de b&uacute;squeda. Esta cadena
                          se puede formar de tres formas diferentes, dependiendo del valor que
                          se le pase al m&eacute;todo <span class="bold"><strong>setTipoConsulta()</strong></span>, teniendo en cuenta que en
                          ninguna de las opciones se distingue por may&uacute;sculas/min&uacute;sculas ni por
                          acentos u otros car&aacute;cteres especiales:
               </p>
               
                       
               <div class="itemizedlist">
                  <ul class="itemizedlist" type="disc">
                     <li class="listitem">
                                    
                        <p><span class="emphasis"><em>Valor 0</em></span>: Se construye la WHERE
                                       igualando los campos a los valores.
                        </p>
                        
                                    
                        <p>Quedar&iacute;a como: <span class="emphasis"><em>campo = valor</em></span>.
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p><span class="emphasis"><em>Valor 1</em></span>: Se construye la WHERE
                                       utilizando el operador LIKE.
                        </p>
                        
                                    
                        <p>Quedar&iacute;a como: <span class="emphasis"><em>campo LIKE
                                             %valor%</em></span></p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p><span class="emphasis"><em>Valor 2</em></span>: Se construye la WHERE
                                       igualando los campos a los valores siempre y cuando estos no
                                       contengan el car&aacute;cter % o _ , en cuyo caso se utilizar&aacute; el
                                       LIKE.
                        </p>
                                  
                     </li>
                  </ul>
               </div>
               
                       
               <p><span class="emphasis"><em>NOTA:</em></span> gvHidra tiene marcado por defecto
                          el<span class="bold"><strong> valor 2 </strong></span>para ejecutar las
                          consultas.
               </p>
               
                       
               <p>El programador fija el tipo de consulta general para toda la
                          aplicaci&oacute;n mediante la propiedad <span class="bold"><strong>queryMode</strong></span> que se encuentra en los ficheros de
                          configuraci&oacute;n, gvHidraConfig.xml. Si surge la necesidad de modificar
                          este comportamiento para un panel se puede hacer uso del m&eacute;todo
                          <span class="bold"><strong>setTipoConsulta()</strong></span> en la clase
                          correspondiente. En las ventanas de selecci&oacute;n tambi&eacute;n se puede
                          configurar la b&uacute;squeda de forma similar con el m&eacute;todo <span class="bold"><strong>setQueryMode()</strong></span>.
               </p>
                     
            </div>
            
                  
            <div class="section" title="3.5.2.3. &iquest;C&oacute;mo inicializamos un panel sin pasar por la b&uacute;squeda?">
               <div class="titlepage">
                  <div>
                     <div>
                        <h4 class="title"><a name="d4e2305"></a>3.5.2.3. &iquest;C&oacute;mo inicializamos un panel sin pasar por la b&uacute;squeda?
                        </h4>
                     </div>
                  </div>
               </div>
                       
               
                       
               <p>Se puede dar el caso de que el programador quiera visualizar
                          directamente los datos sin pasar por el panel de b&uacute;squeda previamente.
                          Esto se puede solucionar d&aacute;ndole en la entrada de menu de la ventana
                          (menuModulos.xml) la url: <span class="bold"><strong>phrame.php?action=ClaseManejadora__buscar</strong></span>.
               </p>
               
                       
               <p>Con esto, se realizar&aacute; la busqueda de forma autom&aacute;tica cargando
                          los datos sin filtros extra.
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">&lt;opcion titulo="Estados" descripcion="Mantenimiento de Estados" url="phrame.php?action=TinvEstados__buscar"/&gt;</pre>
                          </div>
                     
            </div>
            
                  
            <div class="section" title="3.5.2.4. &iquest;C&oacute;mo parametrizar la consulta?">
               <div class="titlepage">
                  <div>
                     <div>
                        <h4 class="title"><a name="d4e2312"></a>3.5.2.4. &iquest;C&oacute;mo parametrizar la consulta?
                        </h4>
                     </div>
                  </div>
               </div>
                       
               
                       
               <p>Puede ser que surja la necesidad de parametrizar la b&uacute;squeda
                          antes de lanzarla. Con este prop&oacute;sito, tenemos el m&eacute;todo <span class="bold"><strong>setParametrosBusqueda()</strong></span>, que se incluir&aacute; en la
                          pre-b&uacute;squeda, para indicarle algunos valores que bien, filtren la
                          SELECT del panel, o que queremos que nos aparezcan. Puede darse el
                          caso de que el filtro a introducir corresponda a un campo que no tiene
                          matching o no sea del tipo campo=valor (is null, EXISTS,...). Por
                          ejemplo: imaginemos que tenemos un panel de b&uacute;squeda sobre datos
                          relativos a facturas en el que hemos introducido una lista desplegable
                          llamada abonada que tiene 3 opciones: "Si", "No" y "". Puede darse el
                          caso que en los datos, para saber si una factura est&aacute; abonada o no,
                          tengamos que comprobar si tiene valor el campo "fechaAbono". &iquest;Como
                          hacemos esto? Utilizando el m&eacute;todo setParametrosBusqueda antes de
                          realizar la b&uacute;squeda.
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">function preBuscar($objDatos)
{
    $abonada = $objDatos-&gt;getValue('abonada')
    if($abonada!='')
    {
        if($abonada=='Si')
            $where = 'fechaAbono is not NULL';
        elseif($abonada=='No')
            $where = 'fechaAbono is NULL';
        <span class="bold"><strong>$this-&gt;setParametrosBusqueda($where);</strong></span>
    }
    return 0;
}</pre>
                          </div>
               
                       
               <p>Tambi&eacute;n podemos a&ntilde;adir condiciones sobre campos de otras tablas
                          relacionadas. Con el m&eacute;todo <span class="bold"><strong>unDiacriticCondition()</strong></span> obtenemos una condici&oacute;n
                          respetando el <span class="bold"><strong>queryMode</strong></span> del
                          formulario (aunque descartando car&aacute;cteres especiales y
                          may&uacute;sculas):
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">function preBuscar($objDatos)
{
    $con = $this-&gt;getConnection();
    $desc = $objDatos-&gt;getValue('descrip_linea');
    if($desc!='')
    {
        $condic_lineas = $con-&gt;unDiacriticCondition('descrip_linea',$desc, $this-&gt;getTipoConsulta());
        $where = 'id_factura in (select id_factura from lineas where '.$condic_lineas.')';
        <span class="bold"><strong>$this-&gt;setParametrosBusqueda($where);</strong></span>
    }
    return 0;
}</pre>
                          </div>
                     
            </div>
            
                  
            <div class="section" title="3.5.2.5. &iquest;C&oacute;mo limitar los registros mostrados?">
               <div class="titlepage">
                  <div>
                     <div>
                        <h4 class="title"><a name="d4e2325"></a>3.5.2.5. &iquest;C&oacute;mo limitar los registros mostrados?
                        </h4>
                     </div>
                  </div>
               </div>
                       
               
                       
               <p>gvHidra por defecto coloca un l&iacute;mite de 100 registros a todas la
                          consultas realizas a partir de la acci&oacute;n buscar, pero esto se puede
                          cambiar a gusto del programador para cada uno de los paneles. Puede
                          darse el caso que un panel tenga una SELECT muy compleja y se quiera
                          limitar el n&uacute;mero de registros mostrados a 20. Esto se puede hacer
                          invocando la funci&oacute;n de negocio <span class="bold"><strong>setLimiteConsulta()</strong></span>.
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">$this-&gt;setLimiteConsulta(25);</pre>
                          </div>
                     
            </div>
            
                  
            <div class="section" title="3.5.2.6. &iquest;C&oacute;mo a&ntilde;adir constantes a una consulta?">
               <div class="titlepage">
                  <div>
                     <div>
                        <h4 class="title"><a name="d4e2331"></a>3.5.2.6. &iquest;C&oacute;mo a&ntilde;adir constantes a una consulta?
                        </h4>
                     </div>
                  </div>
               </div>
                       
               
                       
               <p>Siguiendo con el ejemplo anterior, puede resultar interesante
                          cargar constantes antes de ejecutar la SELECT. Para ello tenemos el
                          m&eacute;todo <span class="bold"><strong>addConstante()</strong></span> que se encarga
                          de a&ntilde;adir la constante en la Select para que aparezca en el
                          DBResult.
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">function preBuscar($objDatos)
{
  $actividad = IgepSession::dameVariable('TinvEstados','Actividad');
  <span class="bold"><strong>$this-&gt;addConstante('Prueba',$actividad);</strong></span>
  return 0;
}</pre>
                          </div>
                     
            </div>
            
                  
            <div class="section" title="3.5.2.7. &iquest;C&oacute;mo conseguir que los campos que componen el filtro mantengan el valor tras pulsar buscar?">
               <div class="titlepage">
                  <div>
                     <div>
                        <h4 class="title"><a name="d4e2338"></a>3.5.2.7. &iquest;C&oacute;mo conseguir que los campos que componen el filtro mantengan
                                   el valor tras pulsar buscar?
                        </h4>
                     </div>
                  </div>
               </div>
                       
               
                       
               <p>Es bastante &uacute;til para un usuario que, tras buscar, pueda
                          mantener en el modo filtro los valores introducidos en dicho filtro.
                          Esto les puede saber para, por ejemplo, saber por que a&ntilde;o han
                          filtrado. gvHidra permite que, activando un flag, se recuerden
                          autom&aacute;ticamente los valores introducidos. Para activar dicho flag (por
                          defecto viene desactivado) debe utilizar en la clase manejadora el
                          m&eacute;todo <span class="bold"><strong>keepFilterValuesAfterSearch()</strong></span>.
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">public function __construct() {
  ...
  <span class="bold"><strong>$this-&gt;keepFilterValuesAfterSearch(true);</strong></span>
  ...
}</pre>
                          </div>
               
                       
               <p>Para hacer uso de esta utilidad, se recomienda distinguir entre
                          los campos del filtro y el listado/edici&oacute;n.
               </p>
                     
            </div>
            
                  
            <div class="section" title="3.5.2.8. &iquest;C&oacute;mo parametrizar el comportamiento despu&eacute;s de la inserci&oacute;n?">
               <div class="titlepage">
                  <div>
                     <div>
                        <h4 class="title"><a name="d4e2346"></a>3.5.2.8. &iquest;C&oacute;mo parametrizar el comportamiento despu&eacute;s de la
                                   inserci&oacute;n?
                        </h4>
                     </div>
                  </div>
               </div>
                       
               
                       
               <p>gvHidra, por defecto, despu&eacute;s de realizar una inserci&oacute;n en el
                          modo listado (searchMode), cambia el filtro para mostrar &uacute;nicamente
                          los nuevos registros insertados, si lo que queremos es volver a
                          realizar la b&uacute;squeda anterior se debe invocar al m&eacute;todo <span class="bold"><strong>showOnlyNewRecordsAfterInsert()</strong></span> con el
                          par&aacute;metro false.
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">public function __construct() 
{   
    ...
    <span class="bold"><strong>$this-&gt;showOnlyNewRecordsAfterInsert(false);</strong></span>
    ...
}
</pre>
                          </div>
                     
            </div>
            
                  
            <div class="section" title="3.5.2.9. &iquest;C&oacute;mo cambiar los filtros que crea el FW?">
               <div class="titlepage">
                  <div>
                     <div>
                        <h4 class="title"><a name="d4e2353"></a>3.5.2.9. &iquest;C&oacute;mo cambiar los filtros que crea el FW?
                        </h4>
                     </div>
                  </div>
               </div>
                       
               
                       
               <p>En gvHidra, al realizar una de las acciones de consulta
                          (buscar/editar), construye una WHERE y la almacena para poder
                          refrescar tras las operaciones de modificaci&oacute;n. Puede que se de el
                          caso, en el que necesitemos cambiar esos filtros para poder visualizar
                          unos registros en concreto (p.e. en un acci&oacute;n particular). Para estos
                          casos, podemos acceder/cambiar dichos filtros con los siguientes
                          m&eacute;todos:
               </p>
               
                       
               <div class="itemizedlist">
                  <ul class="itemizedlist" type="disc">
                     <li class="listitem">
                                    
                        <p>getFilterForSearch(): Obtiene el valor del filtro que se ha
                                       construido sobre la SearchQuery tras la acci&oacute;n de buscar.
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p>setFilterForSearch(): Cambia el valor del filtro que act&uacute;a
                                       sobre SearchQuery.
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p>getFilterForEdit(): Obtiene el valor del filtro que se ha
                                       construido sobre la EditQuery tras la acci&oacute;n de editar.
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p>setFilterForEdit(): Cambia el valor del filtro que act&uacute;a
                                       sobre EditQuery.
                        </p>
                                  
                     </li>
                  </ul>
               </div>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">//Cambia el filtro para SearchQuery
<span class="bold"><strong>$this-&gt;setFilterForSearch("WHERE id=1");</strong></span></pre>
                          </div>
               
                       
               <p><span class="emphasis"><em>Nota</em></span>: si estamos en una acci&oacute;n de interfaz,
                          ser&aacute; necesario recargar la consulta bien con refreshSearch() o
                          refreshEdit().
               </p>
                     
            </div>
                
         </div>
         
             
         <div class="section" title="3.5.3. Acciones no gen&eacute;ricas">
            <div class="titlepage">
               <div>
                  <div>
                     <h3 class="title"><a name="d4e2370"></a>3.5.3. Acciones no gen&eacute;ricas
                     </h3>
                  </div>
               </div>
            </div>
                  
            
                  
            <p>Vamos a explicar ahora como podemos incorporar en una ventana
                     acciones no gen&eacute;ricas.
            </p>
            
                  
            <p>Es bastante com&uacute;n que tengamos ventanas en una aplicaci&oacute;n que
                     tengan un comportamiento no gen&eacute;rico, es decir, que no podamos
                     resolverlas mediante una acci&oacute;n predefinida. Los casos con los que nos
                     podemos encontrar son:
            </p>
            
                  
            <div class="orderedlist">
               <ol class="orderedlist" type="1">
                  <li class="listitem">
                               
                     <p>Generaci&oacute;n de listados.</p>
                             
                  </li>
                  <li class="listitem">
                               
                     <p>Mostrar ventanas emergentes.</p>
                             
                  </li>
                  <li class="listitem">
                               
                     <p>procesos complejos o poco comunes (enviar un correo, procesos
                                  de actualizaci&oacute;n complejos...)
                     </p>
                             
                  </li>
               </ol>
            </div>
            
                  
            <p>Para estos casos se ha incorporado un m&eacute;todo virtual en las clases
                     manejadoras que cede el control de la ejecuci&oacute;n al programador para que
                     pueda realizar las operaciones que estime oportuno.
            </p>
            
                  
            <div class="section" title="3.5.3.1. Acceso a datos">
               <div class="titlepage">
                  <div>
                     <div>
                        <h4 class="title"><a name="d4e2382"></a>3.5.3.1. Acceso a datos
                        </h4>
                     </div>
                  </div>
               </div>
                       
               
                       
               <p><a name="C3AccesoDatos"></a>Antes de explicar como podemos incorporar
                          este tipo de acciones al framework, tenemos que hacer una referencia
                          importante al acceso a los datos. Como ya sabr&eacute;is, el framework tiene
                          una serie de m&eacute;todos de extensi&oacute;n para cada una de las acciones que
                          permiten al programador acceder a los datos y modificarlos. Estos
                          datos a los que se accede siempre van vinculados a la acci&oacute;n que se
                          ejecuta. Por ejemplo para una acci&oacute;n insertar obtendremos los datos
                          que se quieren utilizar para construir la INSERT.
               </p>
               
                       
               <p>Ahora bien, &iquest;qu&eacute; datos vamos a utilizar en una acci&oacute;n
                          particular? Esto depender&aacute; de lo que queramos hacer. Puede que
                          queramos recoger los datos que el usuario haya marcado para borrado
                          para realizar un borrado; puede que queramos los datos que el usuario
                          acaba de introducir como nuevos,...
               </p>
               
                       
               <p>Por todo ello, debemos indicar al framework el conjunto de datos
                          con el que queremos trabajar, para ello debemos utilizar (y es
                          obligatorio para este tipo de acciones) el m&eacute;todo <span class="bold"><strong>setOperacion()</strong></span> de la instancia de
                          IgepComunicaUsuario proporcionada. Este m&eacute;todo admite como par&aacute;metro
                          un string que es el nombre de la operaci&oacute;n sobre la que queremos
                          trabajar. Algunas de las m&aacute;s importantes son:
               </p>
               
                       
               <div class="itemizedlist">
                  <ul class="itemizedlist" type="disc">
                     <li class="listitem">
                                    
                        <p><span class="bold"><strong>insertar</strong></span>: Los datos que el
                                       usuario ha introducido para insertar.
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p><span class="bold"><strong>actualizar/modificar</strong></span>: Los
                                       datos que el usuario ha introducido para modificar.
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p><span class="bold"><strong>borrar</strong></span>: Los datos que el
                                       usuario ha introducido para borrar.
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p><span class="bold"><strong>seleccionar</strong></span>: Los datos que
                                       el usuario ha seleccionado.
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p><span class="bold"><strong>visibles</strong></span>: Los datos que el
                                       usuario tiene visibles en pantalla.
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p><span class="bold"><strong>buscar</strong></span>: Los datos que el
                                       usuario ha introducido en el panel de b&uacute;squeda.
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p><span class="bold"><strong>external</strong></span>: Los valores de
                                       los campos external (ver campos especiales).
                        </p>
                                  
                     </li>
                  </ul>
               </div>
               
                       
               <p>Cambiando entre las operaciones podremos acceder a los datos
                          correspondientes.
               </p>
                     
            </div>
            
                  
            <div class="section" title="3.5.3.2. Implementaci&oacute;n de una acci&oacute;n particular">
               <div class="titlepage">
                  <div>
                     <div>
                        <h4 class="title"><a name="d4e2411"></a>3.5.3.2. Implementaci&oacute;n de una acci&oacute;n particular
                        </h4>
                     </div>
                  </div>
               </div>
                       
               
                       
               <p>A continuaci&oacute;n iremos relatando paso a paso como a&ntilde;adir acciones
                          particulares a una ventana.
               </p>
               
                       
               <p>En primer lugar tenemos que a&ntilde;adir un est&iacute;mulo en la pantalla
                          que lance dicha acci&oacute;n, t&iacute;picamente un bot&oacute;n. Para ello debemos a&ntilde;adir
                          en la tpl, un bot&oacute;n que lance la acci&oacute;n. Lo indicaremos con los
                          par&aacute;metros <span class="bold"><strong>accion</strong></span> y <span class="bold"><strong>action</strong></span>:
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">{CWBoton imagen="50" texto="Generar" class="boton" accion="particular" action="<span class="bold"><strong>nombreDeTuOperacion</strong></span>"}</pre>
                          </div>
               
                       
               <p>Una vez creado el disparador en la pantalla, debemos indicar que
                          clase debe gestionar la acci&oacute;n y que posibles destinos tendr&aacute; de
                          respuesta. Para ello, en el fichero <span class="emphasis"><em>mappings.php
                                </em></span>a&ntilde;adimos la siguiente informaci&oacute;n:
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">$this-&gt;_AddMapping('claseManejadora__<span class="bold"><strong>nombreDeTuOperacion</strong></span>', 'claseManejadora');  
$this-&gt;_AddForward('claseManejadora__<span class="bold"><strong>nombreDeTuOperacion</strong></span>', '<span class="bold"><strong>operacionOk</strong></span>', 
       'index.php?view=views/ubicacioFicheroViewsClaseManejadora.php&amp;panel=buscar'); 
$this-&gt;_AddForward('claseManejadora__<span class="bold"><strong>nombreDeTuOperacion</strong></span>', '<span class="bold"><strong>operacionError</strong></span>', 
       'index.php?view=views/ubicacioFicheroViewsClaseManejadora.php&amp;panel=buscar');</pre>
                          </div>
               
                       
               <p>Finalmente, en la clase manejadora debemos extender el m&eacute;todo
                          <span class="bold"><strong>accionesParticulares()</strong></span> para poder
                          recibir el control de la ejecuci&oacute;n y realizar las operaciones
                          oportunas. El c&oacute;digo ser&iacute;a:
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">class claseManejadora extends gvHidraForm 
{

...

    public function accionesParticulares($str_accion, $objDatos) 
    {

        switch($str_accion) 
        {
            case "nombreDeTuOperacion":

                // En el ejemplo usamos:
                // -comunicacion de errores mediante excepcion.
                // -recojida de datos seleccionados en pantalla.
                // -creacion de instancias de clases de negocio (podrian 
ser llamadas estaticas).
                try {
                    //Recojo valores de las tuplas seleccionadas
                    $objDatos-&gt;setOperacion('seleccionar');
                    $datos = $objDatos-&gt;getAllTuplas();

                    //Llamamos a la clase de negocio                    
                    $f = new funciones();
                    $f-&gt;miMetodo($datos);
                    $actionForward = 
$objDatos-&gt;getForward('<span class="bold"><strong>operacionOk</strong></span>');
                }
                catch(Exception $e) 
                {
                   //Mostramos mensaje de error
                   $this-&gt;showMensaje('APL-01');
                   $actionForward = 
$objDatos-&gt;getForward('<span class="bold"><strong>operacionError</strong></span>');
                }
                break;

            case "nombreDeTuOperacion2":
                ...
                break;
        }
        return $actionForward;
   }</pre>
                          </div>
               
                       
               <p>Antes de una acci&oacute;n particular SIEMPRE tenemos que indicar el
                          tipo de datos a los que queremos acceder, lo haremos con <span class="bold"><strong>setOperacion()</strong></span>. Recordemos que tenemos
                          diferentes operaciones (insertar, modificar, borrar, seleccionar,
                          visibles, external...)
               </p>
               
                       
               <p>El m&eacute;todo <span class="bold"><strong>accionesParticulares()</strong></span> debe devolver un
                          objeto<span class="bold"><strong> actionForward</strong></span> v&aacute;lido. Tenemos
                          acceso a los forwards de nuestra acci&oacute;n a trav&eacute;s del m&eacute;todo <span class="bold"><strong>getForward</strong></span> del objeto de datos (en el ejemplo
                          $objDatos).
               </p>
                     
            </div>
            
                  
            <div class="section" title="3.5.3.3. Ejemplo de listado">
               <div class="titlepage">
                  <div>
                     <div>
                        <h4 class="title"><a name="d4e2441"></a>3.5.3.3. Ejemplo de listado
                        </h4>
                     </div>
                  </div>
               </div>
                       
               
                       
               <p>Un caso t&iacute;pico, es el de los listados. El procedimiento es el
                          mismo al explicado anteriormente, pero debemos a&ntilde;adir a la generaci&oacute;n
                          de listado la posibilidad de generarse en una ventana emergente. Para
                          ello debemos hacer uso del m&eacute;todo <span class="bold"><strong>openWindow</strong></span> pas&aacute;ndole el forward de destino. Por
                          ejemplo:
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">class claseManejadora extends gvHidraForm 
{
  ...

   public function accionesParticulares($str_accion, $objDatos) 
   {
        ...
        //Si todo est&aacute; Ok
        //Abrimos una nueva ventana donde mostraremos el listado
        $actionForward = $objDatos-&gt;getForward('mostrarListado');
        $this-&gt;openWindow($actionForward);

        //En la ventana actual mostramos un mensaje indicando que el listado se ha generado
        //y volvemos a la ruta deseada
        $this-&gt;showMensaje('APL-29');
        $actionForward = $objDatos-&gt;getForward('<span class="bold"><strong>operacionOk</strong></span>');
    }
}</pre>
                          </div>
               
                       
               <p>Para obtener mas informacion sobre los informes y Jasper Report,
                          acudid a la documentacion en el capitulo x
               </p>
                     
            </div>
                
         </div>
         
             
         <div class="section" title="3.5.4. Acciones de interfaz">
            <div class="titlepage">
               <div>
                  <div>
                     <h3 class="title"><a name="d4e2449"></a>3.5.4. Acciones de interfaz
                     </h3>
                  </div>
               </div>
            </div>
                  
            
                  
            <div class="section" title="3.5.4.1. Definici&oacute;n">
               <div class="titlepage">
                  <div>
                     <div>
                        <h4 class="title"><a name="d4e2451"></a>3.5.4.1. Definici&oacute;n
                        </h4>
                     </div>
                  </div>
               </div>
                       
               
                       
               <p>Las acciones de interfaz en gvHidra es todo aquel est&iacute;mulo de
                          pantalla que se resuelve con un cambio de la interfaz sin recarga de
                          la ventana. Es decir, t&iacute;picamente el uso de tecnolog&iacute;a AJAX para
                          actualizar la interfaz sin que el usuario perciba una recarga de la
                          p&aacute;gina. Algunos ejemplos de acciones que podemos necesitar son:
               </p>
               
                       
               <div class="itemizedlist">
                  <ul class="itemizedlist" type="disc">
                     <li class="listitem">
                                    
                        <p>Cuando pierda el foco un campo, actualizar un campo
                                       descripci&oacute;n (t&iacute;pica descripci&oacute;n de claves ajenas)
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p>Dependiendo del valor de un desplegable (HTML select),
                                       mostrar/ocultar un campo en pantalla.
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p>Cuando marcamos/desmarcamos un checkbox,
                                       habilitar/deshabilitar un campo.
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p>...</p>
                                  
                     </li>
                  </ul>
               </div>
               
                       
               <p>Para ello, el framework intenta simplificar el uso de estas
                          acciones de forma que el programador centrar&aacute; sus esfuerzos en la
                          clase manejadora (en PHP); dejando que la herramienta se encargue de
                          la generaci&oacute;n de Javascript. Actualmente el framework utiliza un
                          iframe oculto que recoge el est&iacute;mulo de pantalla, lo direcciona a la
                          clase manejadora correspondiente y recibe la respuesta en formato
                          Javascript.
               </p>
                     
            </div>
            
                  
            <div class="section" title="3.5.4.2. Uso de las acciones de interfaz">
               <div class="titlepage">
                  <div>
                     <div>
                        <h4 class="title"><a name="d4e2464"></a>3.5.4.2. Uso de las acciones de interfaz
                        </h4>
                     </div>
                  </div>
               </div>
                       
               
                       
               <p>El primer paso para definir una acci&oacute;n de interfaz es indicar en
                          la TPL que el campo tiene que disparar dicha acci&oacute;n.
               </p>
               
                       
               <p>En la tpl hemos incluido el siguiente c&oacute;digo:</p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">{CWCampoTexto nombre="cif" editable="true" size="13" textoAsociado="Cif"} 
&amp;nbsp;
{CWCampoTexto nombre="<span class="bold"><strong>orden</strong></span>" editable="true" size="2" textoAsociado="Orden" <span class="bold"><strong>actualizaA="nombre"</strong></span>}
&amp;nbsp;{CWCampoTexto nombre="<span class="bold"><strong>nombre</strong></span>" editable="false" size="40"}</pre>
                          </div>
               
                       
               <p>Se ha a&ntilde;adido la propiedad <span class="bold"><strong>actualizaA.</strong></span> Esta propiedad le indica a la clase
                          que cuando pierda el foco el campo <span class="emphasis"><em>orden </em></span>se tiene
                          que lanzar una acci&oacute;n de interfaz, el valor de esta propiedad ser&aacute; el
                          nombre del campo o campos destino de la acci&oacute;n de interfaz (p.ej.
                          actualizaA="nombre, apellidos").
               </p>
               
                       
               <p>Ahora, en la clase, debemos indicar que <span class="emphasis"><em>acci&oacute;n de
                                interfaz</em></span> corresponder&aacute; con la p&eacute;rdida de foco de dicho
                          campo. Para ello incluimos en el constructor de la clase manejadora el
                          siguiente c&oacute;digo:
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">//Para las validaciones cuando introduzca el proveedor 
$this-&gt;addAccionInterfaz('<span class="bold"><strong>orden</strong></span>','manejadorProveedor');</pre>
                          </div>
               
                       
               <p>En el m&eacute;todo se introduce el nombre del campo de la tpl que
                          lanzar&aacute; la validaci&oacute;n y el nombre del m&eacute;todo que el programador va a
                          implementar para realizar la validaci&oacute;n.
               </p>
               
                       
               <p>La implementaci&oacute;n del m&eacute;todo se hace en la clase asociada al
                          panel:
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">public function manejadorProveedor ($objDatos) //Manejador del evento
{
  $cif = $objDatos-&gt;getValue('cif');
  $orden = $objDatos-&gt;getValue('orden');  

  if($cif!='' and $orden!='')
  {
     if (!$this-&gt;validaCif($cif))//Validaci&oacute;n l&eacute;xica
     {         
        $this-&gt;showMensaje('APL-04',array($cif));
        return -1
     }

     $proveedor = $this-&gt;obtenerProveedor($cif, $orden);
     if ($proveedor == null) // Validaci&oacute;n sem&aacute;ntica
     {         
        $this-&gt;showMensaje('APL-24',array($cif,$orden));
        return -1
     }
     else
     {
        $objDatos-&gt;setValue('nombre',$proveedor);
     }
  }
  else
     $objDatos-&gt;setValue('nombre','');
  return 0;
}

public function validarCif ($cif, $orden)
{
...
}

public function obtenerProveedor($cif, $orden)
{
  $res = $this-&gt;consultar("select * from tcom_proveed where nif = '".$cif."' and orden = ".$orden );	
  if(count($res)&gt;0)
  {
     return($res[0]['nombre']);
  }
  else
  {     
     return(null);
  }
}</pre>
                          </div>
               
                       
               <p>En resumen, el ejemplo anterior realizar&aacute; una comprobaci&oacute;n de
                          los campos cif y orden, una vez rellenados por el usuario
                          (concretamente cuando pierda el foco el campo orden), lanzando el
                          m&eacute;todo <span class="emphasis"><em>manejadorProveedor()</em></span> y tendr&aacute; el resultado
                          si el cif y el orden es correcto. En caso contrario, el resultado ser&aacute;
                          alguno de los mensajes de error que el programador haya
                          capturado.
               </p>
               
                       
               <p>En general, la interfaz y el uso de estos m&eacute;todos es parecida a
                          la de cualquier m&eacute;todo pre o post operaci&oacute;n. Si devuelven 0 se
                          considera que todo ha ido correctamente y si devuelve -1 que se ha
                          encontrado un error.
               </p>
               
                       
               <p>Sin embargo, estos m&eacute;todos tienen una peculiaridad especial,
                          adem&aacute;s de las funcionalidades de las que dispone un m&eacute;todo pre o post
                          operaci&oacute;n (como sabemos, se permite el acceso a los datos que hay en
                          pantalla mediante la variable $objDatos, se pueden realizar consultas
                          sobre la fuente de datos del panel, ...) pueden modificar aspectos de
                          estado de la interfaz como el contenido, la visibilidad o la
                          accesibilidad de los componentes de pantalla. Para ello debemos hacer
                          uso de los siguientes m&eacute;todos:
               </p>
               
                       
               <div class="itemizedlist">
                  <ul class="itemizedlist" type="disc">
                     <li class="listitem">
                                    
                        <p><span class="bold"><strong>getValue($campo)</strong></span>: Obtiene
                                       el valor de un campo
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p><span class="bold"><strong>setValue($campo,$valor)</strong></span>:
                                       Cambia el valor de un campo
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p><span class="bold"><strong>setVisible($campo,$valor)</strong></span>:
                                       Cambia la visibilidad de un campo
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p><span class="bold"><strong>setSelected($campo,$valor)</strong></span>:
                                       Cambia el valor seleccionado de una lista.
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p><span class="bold"><strong>setEnable($campo,$valor)</strong></span>:
                                       Cambia la accesibilidad de un campo.
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p><span class="bold"><strong>posicionarEnFicha($indiceFila)</strong></span>: Nos permite
                                       cambiar la ficha activa.
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p><span class="bold"><strong>getModoActivo()</strong></span>: Devuelve
                                       el modo que dispara la acci&oacute;n.
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p><span class="bold"><strong>getTriggerField()</strong></span>: Devuelve
                                       el campo que lanza la acci&oacute;n de interfaz.
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p><span class="bold"><strong>setBttlState($idPanel, $nameBttl,
                                             $on)</strong></span>: Habilita o deshabilita el botonTooltip b&aacute;sico
                                       ('insertar', 'modificar', 'restaurar') del panel indicado.
                        </p>
                                  
                     </li>
                  </ul>
               </div>
               
                       
               <p>Ejemplo:</p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">//Fijar la visibilidad de un campo
$objDatos-&gt;<span class="bold"><strong>setVisible</strong></span>('nfactura',true);
$objDatos-&gt;<span class="bold"><strong>setVisible</strong></span>('nfactura',false);
//Fija la accesibilidad de un campo
$objDatos-&gt;<span class="bold"><strong>setEnable</strong></span>('nfactura',true);
$objDatos-&gt;<span class="bold"><strong>setEnable</strong></span>('nfactura',false);
//Fija el contenido de un campo
$objDatos-&gt;<span class="bold"><strong>getValue</strong></span>('nfactura');
$objDatos-&gt;<span class="bold"><strong>setValue</strong></span>('nfactura','20');

//Deshabilita el boton Tooltip de inserci&oacute;n:
$objDatos-&gt;<span class="bold"><strong>setBttlState</strong></span>('edi', 'insertar', false);

//Obtienen informaci&oacute;n sobre el modo que dispara la acci&oacute;n (FIL-LIS-EDI)
$objDatos-&gt;<span class="bold"><strong>getModoActivo</strong></span>();</pre>
                          </div>
                     
            </div>
                
         </div>
           
      </div>
      <div class="navfooter">
         <hr>
         <table width="100%" summary="Navigation footer">
            <tr>
               <td width="40%" align="left"><a accesskey="p" href="ch03s04.html">Anterior</a>&nbsp;
               </td>
               <td width="20%" align="center"><a accesskey="u" href="ch03.html">Subir</a></td>
               <td width="40%" align="right">&nbsp;<a accesskey="n" href="ch03s06.html">Siguiente</a></td>
            </tr>
            <tr>
               <td width="40%" align="left" valign="top">3.4. Dise&ntilde;o de pantalla con smarty/plugins&nbsp;</td>
               <td width="20%" align="center"><a accesskey="h" href="indice.html">Inicio</a></td>
               <td width="40%" align="right" valign="top">&nbsp;3.6. Personalizando el estilo</td>
            </tr>
         </table>
      </div>
   </body>
</html>